/*
* EuroCarbDB, a framework for carbohydrate bioinformatics
*
* Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
* A copy of this license accompanies this distribution in the file LICENSE.txt.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* Last commit: $Rev: 1210 $ by $Author: glycoslave $ on $Date:: 2009-06-12 #$
*/
/**
@author Alessio Ceroni (a.ceroni@imperial.ac.uk)
*/
package org.eurocarbdb.application.glycoworkbench.plugin.reporting;
import org.eurocarbdb.application.glycoworkbench.plugin.*;
import org.eurocarbdb.application.glycoworkbench.*;
import org.eurocarbdb.application.glycanbuilder.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.print.*;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.data.general.Dataset;
import org.jfree.data.category.CategoryDataset;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.ui.TextAnchor;
import static org.eurocarbdb.application.glycanbuilder.Geometry.*;
public class ProfilesComparisonReportChartCanvas extends JComponent implements SVGUtils.Renderable, Printable {
private static final int DRAW_X_MARGIN = 20;
private static final int DRAW_Y_MARGIN = 20;
private static final int CHART_X_MARGIN = 20;
private static final int CHART_Y_MARGIN = 20;
private static final int CHART_WIDTH = 800;
private static final int CHART_WIDTH_TICK = 15;
private static final int CHART_HEIGHT = 600;
private GlycoWorkbench theApplication;
private ProfilesComparisonReportDocument theDocument;
private GlycanRenderer theGlycanRenderer;
private JScrollPane theScrollPane = null;
private ProfilesComparisonReportOptions theOptions;
private GraphicOptions theGraphicOptions;
private CategoryDataset theDataset;
private CategoryPlot thePlot;
private JFreeChart theChart;
// drawing
private double scale;
private boolean is_printing;
private Rectangle view_area;
private Rectangle draw_area;
private Rectangle chart_area;
private Rectangle2D data_area;
// construction
public ProfilesComparisonReportChartCanvas(GlycoWorkbench application, ProfilesComparisonReportDocument doc, ProfilesComparisonReportOptions opt) {
theApplication = application;
theDocument = doc;
theOptions = opt;
theGraphicOptions = theApplication.getWorkspace().getGraphicOptions();
theGlycanRenderer = theApplication.getWorkspace().getGlycanRenderer();
// create chart
createChart();
// finish setting up
is_printing = false;
setScale(1.);
}
public void setScrollPane(JScrollPane sp) {
theScrollPane = sp;
}
// drawing
public void beforeRendering() {
is_printing = true;
}
public void afterRendering() {
is_printing = false;
}
public Dimension getRenderableSize() {
return getPreferredSize();
}
public void paintRenderable(Graphics2D g2d) {
paintComponent(g2d);
}
protected void paintComponent(Graphics g) {
// prepare graphic object
Graphics2D g2d = (Graphics2D)g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// set clipping area
if( is_printing ) {
g2d.translate(-draw_area.x,-draw_area.y);
g2d.setClip(draw_area);
}
//paint canvas background
if( !is_printing ) {
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
}
// paint white background on drawing area
g2d.setColor(Color.white);
g2d.fillRect(draw_area.x, draw_area.y, draw_area.width, draw_area.height);
if( !is_printing ) {
g2d.setColor(Color.black);
g2d.draw(draw_area);
}
// paint
paintChart(g2d);
// dispose graphic object
g2d.dispose();
revalidate();
}
protected void paintChart(Graphics2D g2d) {
org.jfree.chart.ChartRenderingInfo cri = new org.jfree.chart.ChartRenderingInfo();
theChart.draw(g2d,chart_area,cri);
data_area = cri.getPlotInfo().getDataArea();
}
public Dimension getPreferredSize() {
if( is_printing )
return draw_area.getSize();
return view_area.getSize();
}
public Dimension getMinimumSize() {
return new Dimension(0,0);
}
// actions
public void print( PrinterJob job ) throws PrinterException {
// do something before
is_printing = true;
job.print();
// do something after
is_printing = false;
}
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex > 0) {
return NO_SUCH_PAGE;
}
else {
Graphics2D g2d = (Graphics2D)g;
g2d.setBackground(Color.white);
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
Dimension td = this.getPreferredSize();
double sx = pageFormat.getImageableWidth()/td.width;
double sy = pageFormat.getImageableHeight()/td.height;
double s = Math.min(sx,sy);
if( s<1. )
g2d.scale(s,s);
RepaintManager.currentManager(this).setDoubleBufferingEnabled(false);
this.paint(g2d);
RepaintManager.currentManager(this).setDoubleBufferingEnabled(true);
return PAGE_EXISTS;
}
}
public void setScale(double scale) {
this.scale = scale;
updateView();
}
public double getScale() {
return this.scale;
}
public void getScreenshot() {
ClipUtils.setContents(SVGUtils.getImage(this));
}
public void updateView() {
updateDrawArea();
repaint();
}
private void createChart() {
// create dataset
theDataset = createDataset();
// create axis
CategoryAxis categoryAxis = new CategoryAxis("");
categoryAxis.setCategoryLabelPositions(org.jfree.chart.axis.CategoryLabelPositions.UP_45);
ValueAxis valueAxis = new NumberAxis("Normalized Intensities");
// create renderer
CategoryItemRenderer renderer = null;
if( theOptions.REPRESENTATION==theOptions.BARS )
renderer = new org.jfree.chart.renderer.category.BarRenderer();
else if( theOptions.REPRESENTATION==theOptions.ERRORBARS )
renderer = new org.jfree.chart.renderer.category.StatisticalBarRenderer();
else if( theOptions.REPRESENTATION==theOptions.DISTRIBUTIONS )
renderer = new org.jfree.chart.renderer.category.ScatterRenderer();
ItemLabelPosition position1 = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER);
renderer.setBasePositiveItemLabelPosition(position1);
ItemLabelPosition position2 = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_CENTER);
renderer.setBaseNegativeItemLabelPosition(position2);
// create plot
thePlot = new CategoryPlot(theDataset, categoryAxis, valueAxis, renderer);
thePlot.setOrientation(org.jfree.chart.plot.PlotOrientation.VERTICAL);
// add mean values
if( theOptions.REPRESENTATION==theOptions.DISTRIBUTIONS ) {
thePlot.setDataset(1, createMeansDataset());
thePlot.mapDatasetToRangeAxis(1, 0);
CategoryItemRenderer lr = new org.jfree.chart.renderer.category.LevelRenderer();
lr.setPaint(Color.black);
thePlot.setRenderer(1,lr);
}
// create chart
theChart = new JFreeChart("", JFreeChart.DEFAULT_TITLE_FONT, thePlot, true);
theChart.setBackgroundPaint(Color.white);
theChart.setBorderVisible(false);
}
private CategoryDataset createDataset() {
GlycanRenderer theRenderer = theApplication.getWorkspace().getGlycanRenderer();
if( theOptions.REPRESENTATION==theOptions.BARS ) {
org.jfree.data.category.DefaultCategoryDataset ret = new org.jfree.data.category.DefaultCategoryDataset();
for( ProfilesComparisonReportDocument.Row row : theDocument.getRows() ) {
for( int i=0; i<theDocument.getNoColumns(); i++ )
ret.addValue(row.getColumn(i),theDocument.getNames().get(i),row.name);
}
return ret;
}
else if( theOptions.REPRESENTATION==theOptions.ERRORBARS ) {
org.jfree.data.statistics.DefaultStatisticalCategoryDataset ret = new org.jfree.data.statistics.DefaultStatisticalCategoryDataset();
for( ProfilesComparisonReportDocument.Row row : theDocument.getRows() ) {
ret.add(mean(row.intensities_firstgroup),stddev(row.intensities_firstgroup),"First group",row.name);
ret.add(mean(row.intensities_secondgroup),stddev(row.intensities_secondgroup),"Second group",row.name);
}
return ret;
}
else if( theOptions.REPRESENTATION==theOptions.DISTRIBUTIONS ) {
org.jfree.data.statistics.DefaultMultiValueCategoryDataset ret = new org.jfree.data.statistics.DefaultMultiValueCategoryDataset();
for( ProfilesComparisonReportDocument.Row row : theDocument.getRows() ) {
ret.add(tolist(row.intensities_firstgroup),"First group",row.name);
ret.add(tolist(row.intensities_secondgroup),"Second group",row.name);
}
return ret;
}
return null;
}
private CategoryDataset createMeansDataset() {
GlycanRenderer theRenderer = theApplication.getWorkspace().getGlycanRenderer();
org.jfree.data.category.DefaultCategoryDataset ret = new org.jfree.data.category.DefaultCategoryDataset();
for( ProfilesComparisonReportDocument.Row row : theDocument.getRows() ) {
ret.addValue(mean(row.intensities_firstgroup),"First group",row.name);
ret.addValue(mean(row.intensities_secondgroup),"Second group",row.name);
}
return ret;
}
private ArrayList<Double> tolist(double[] array) {
ArrayList<Double> ret = new ArrayList<Double>();
for( double d : array )
ret.add(d);
return ret;
}
private ArrayList<Double> tolist(double value) {
ArrayList<Double> ret = new ArrayList<Double>();
ret.add(value);
return ret;
}
private double mean(double[] array) {
if( array==null || array.length==0 )
return 0.;
double mean = 0.;
for( int i=0; i<array.length; i++ )
mean += array[i];
return mean/(double)array.length;
}
private double stddev(double[] array) {
if( array==null || array.length==0 )
return 0.;
double mean = mean(array);
double smean = 0.;
for( int i=0; i<array.length; i++ )
smean += array[i]*array[i];
return Math.sqrt(smean/(double)array.length - mean*mean);
}
private Rectangle getViewArea(double scale) {
int chart_width = Math.max(CHART_WIDTH,CHART_WIDTH_TICK*theDocument.getNoRows());
return new Rectangle(0,0,(int)(2*DRAW_X_MARGIN + scale*(2*CHART_X_MARGIN + chart_width)),(int)(2*DRAW_Y_MARGIN + scale*(2*CHART_X_MARGIN + CHART_HEIGHT)));
}
private Rectangle getDrawArea(double scale) {
int chart_width = Math.max(CHART_WIDTH,CHART_WIDTH_TICK*theDocument.getNoRows());
return new Rectangle(DRAW_X_MARGIN,DRAW_Y_MARGIN,(int)(scale*(2*CHART_X_MARGIN + chart_width)),(int)(scale*(2*CHART_Y_MARGIN + CHART_HEIGHT)));
}
private Rectangle getChartArea(double scale) {
int chart_width = Math.max(CHART_WIDTH,CHART_WIDTH_TICK*theDocument.getNoRows());
return new Rectangle((int)(DRAW_X_MARGIN + scale*CHART_X_MARGIN),(int)(DRAW_Y_MARGIN + scale*CHART_Y_MARGIN),(int)(scale*chart_width),(int)(scale*CHART_HEIGHT));
}
protected void updateDrawArea() {
// update data area
view_area = getViewArea(scale);
draw_area = getDrawArea(scale);
chart_area = getChartArea(scale);
data_area = null;
paintChart(GraphicUtils.createImage(view_area.getSize(),true).createGraphics());
}
}